package demo.dcs.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * created by dongbo on 2019/10/18
 */
public class ObjectBytesUtil {
    private static final Logger logger = LoggerFactory.getLogger(ObjectBytesUtil.class);

    //统计bytes大小,上层是异步
    public static long objectToByteLength(Object obj) {
//        Long startTime = System.currentTimeMillis();
//        //null 返回0
        if(!isSerializable(obj)) {
            return 0L;
        }

        byte[] bytes = objectToBytes(obj);
        long size = bytes.length;

//        Long endTime = System.currentTimeMillis();
//        if(endTime - startTime > 1){
//            logger.warn("xdcs ObjectBytesUtil objectToByteLength cost: " + (endTime - startTime) + "ms"
//                + ", size: " + size);
//            System.err.println("xdcs ObjectBytesUtil objectToByteLength cost: " + (endTime - startTime) + "ms"
//                    + ", size: " + size);
//        }

        return size;
    }

    //object转为bytes，用于统计大小
    private static byte[] objectToBytes(Object obj){
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        byte[] bytes = new byte[0];
        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();
            bytes = bos.toByteArray();
        } catch (Exception e) {
            logger.warn("objectToByteArray error: ", e);
        }finally {
            if(oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    logger.warn("ObjectBytesUtil oos.close() error: ", e);
                }
            }

            if(bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    logger.warn("ObjectBytesUtil bos.close() error: ", e);
                }
            }
        }

        return bytes;
    }

    //主要用于jedis的参数和结果的类型判断
    private static boolean isSerializable(Object object){
        if(object == null || !(object instanceof Serializable)){
            return false;
        }

        if(object instanceof String || object instanceof byte[]){
            return true;
        }

        if(object instanceof List){
            List list = (List)object;
            if(list.size() > 0) {
                Object list0 = list.get(0);
                if (list0 instanceof Serializable) {
                    return true;
                }
            }
        }

        if(object instanceof Set){
            Set set = (Set)object;
            Iterator iterator = set.iterator();
            if(iterator.hasNext()){
                Object set0 = iterator.next();
                if(set0 instanceof Serializable){
                    return true;
                }
            }
        }

        return false;
    }
}
